﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CuitControlBase.cs" company="">
// </copyright>
// <summary>
//   The cuit control base.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace UITest.CUIT.CuitControls
{
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Windows.Input;

    using Microsoft.VisualStudio.TestTools.UITesting;

    using UITest.CUIT.CuitControls.Extension;
    using UITest.Report;

    /// <summary>
    /// The cuit control base.
    /// </summary>
    /// <typeparam name="T">
    /// </typeparam>
    public class CuitControlBase<T> : ICuitControlBase
        where T : UITestControl
    {
        #region Fields

        /// <summary>
        ///     The search properties.
        /// </summary>
        protected PropertyExpressionCollection SearchProperties;

        /// <summary>
        ///     The _control.
        /// </summary>
        protected T _control;

        /// <summary>
        ///     The browser Window.
        /// </summary>
        protected BrowserWindow browserwindow;

        /// <summary>
        ///     The filterproperties in string.
        /// </summary>
        protected string filterPropertiesInString;

        /// <summary>
        ///     The search properties in string.
        /// </summary>
        protected string searchPropertiesInString;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="CuitControlBase{T}" /> class.
        /// </summary>
        public CuitControlBase()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CuitControlBase{T}"/> class.
        /// </summary>
        /// <param name="browserWindow">
        /// The browser window.
        /// </param>
        public CuitControlBase(BrowserWindow browserWindow)
        {
            this.browserwindow = browserWindow;
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets a value indicating whether enabled.
        /// </summary>
        public bool Enabled
        {
            get
            {
                this._control.WaitForControlReady();
                return this._control.Enabled;
            }
        }

        /// <summary>
        ///     Gets a value indicating whether exists.
        /// </summary>
        public bool Exists
        {
            get
            {
                if (this._control == null)
                {
                    return false;
                }

                return this._control.Exists;
            }
        }

        /// <summary>
        ///     Gets the parent.
        /// </summary>
        public virtual ICuitControlBase Parent
        {
            get
            {
                return null;
            }
        }

        #endregion

        #region Properties

        /// <summary>
        ///     The report.
        /// </summary>
        protected ReportListener Report
        {
            get
            {
                return ReportFactory.GetReportListener();
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        ///     The click.
        /// </summary>
        public void Click()
        {
            this.WriteTestOutput("Click on ");
            this._control.WaitForControlReady();
            Playback.Wait(500);
            Point pt = this._control.GetControlCentre();
            Playback.Wait(500);
            Mouse.Click(pt);
        }

        /// <summary>
        /// The click.
        /// </summary>
        /// <param name="pt">
        /// The pt.
        /// </param>
        public void Click(Point pt)
        {
            this.WriteTestOutput("Click on ");
            this._control.WaitForControlReady();
            Playback.Wait(500);
            Mouse.Click(pt);
            Playback.Wait(500);
        }

        /// <summary>
        ///     The double click.
        /// </summary>
        public void DoubleClick()
        {
            this._control.WaitForControlReady();
            this.WriteTestOutput("Double Click on " );
            Point pt = this._control.GetControlCentre();
            Mouse.DoubleClick(pt);
        }

        /// <summary>
        ///     The draw highlight.
        /// </summary>
        public void DrawHighlight()
        {
            this._control.DrawHighlight();
        }

        /// <summary>
        ///     The find matching controls.
        /// </summary>
        /// <returns>
        ///     The <see cref="UITestControlCollection" />.
        /// </returns>
        public UITestControlCollection FindMatchingControls()
        {
            return this._control.FindMatchingControls();
        }

        /// <summary>
        ///     The get.
        /// </summary>
        /// <typeparam name="T1">
        /// </typeparam>
        /// <returns>
        ///     The <see cref="T1" />.
        /// </returns>
        public T1 Get<T1>() where T1 : ICuitControlBase
        {
            var control = Activator.CreateInstance<T1>();

            object baseControl = Activator.CreateInstance(control.GetBaseType(), new object[] { this.UnWrap() });

            control.Wrap(baseControl);

            return control;
        }

        /// <summary>
        ///     The get base type.
        /// </summary>
        /// <returns>
        ///     The <see cref="Type" />.
        /// </returns>
        public Type GetBaseType()
        {
            return typeof(T);
        }

        /// <summary>
        /// The get control from matching contorl collection.
        /// </summary>
        /// <param name="index">
        /// The index.
        /// </param>
        /// <returns>
        /// The <see cref="T"/>.
        /// </returns>
        public T GetControlFromMatchingContorlCollection(int index)
        {
            UITestControlCollection controlcollection = this._control.FindMatchingControls();
            this._control = (T)controlcollection[index];
            return this._control;
        }

        /// <summary>
        ///     The get microsoft test control.
        /// </summary>
        /// <returns>
        ///     The <see cref="UITestControl" />.
        /// </returns>
        public UITestControl GetMicrosoftTestControl()
        {
            return this._control;
        }

        /// <summary>
        ///     The get parent microsoft control.
        /// </summary>
        /// <returns>
        ///     The <see cref="UITestControl" />.
        /// </returns>
        public UITestControl GetParentMicrosoftControl()
        {
            return this._control.GetParent();
        }

        /// <summary>
        /// The get property.
        /// </summary>
        /// <param name="propertyName">
        /// The property name.
        /// </param>
        /// <returns>
        /// The <see cref="object"/>.
        /// </returns>
        public object GetProperty(string propertyName)
        {
            return this._control.GetProperty(propertyName);
        }

        /// <summary>
        ///     The hover.
        /// </summary>
        public void Hover()
        {
            this._control.WaitForControlReady();
            this.WriteTestOutput("Hover on ");
            Mouse.Hover(this._control);
        }

        /// <summary>
        ///     The right click.
        /// </summary>
        public void RightClick()
        {
            this._control.WaitForControlReady();
            this.WriteTestOutput("Right Click on ");
            Point pt = this._control.GetControlCentre();
            Mouse.Click(MouseButtons.Right, ModifierKeys.None, pt);
        }

        /// <summary>
        /// The set browser window.
        /// </summary>
        /// <param name="testControl">
        /// The test control.
        /// </param>
        public void SetBrowserWindow(UITestControl testControl)
        {
            this.browserwindow = BrowserWindow.Locate(testControl.TopParent.Name);
            this.WriteTestOutput("Set Browser Window on " );
        }

        /// <summary>
        ///     The set focus.
        /// </summary>
        public void SetFocus()
        {
            this._control.WaitForControlReady();
            this._control.SetFocus();
            this.WriteTestOutput("Set Focus on " );
        }

        /// <summary>
        ///     The underlying UITestControl instance. For example, returns HtmlEdit in case of CuitHtmlEdit.
        /// </summary>
        /// <returns>
        ///     The <see cref="T" />.
        /// </returns>
        public T UnWrap()
        {
            return this._control;
        }

        /// <summary>
        ///     The wait for control enabled.
        /// </summary>
        /// <returns>
        ///     The <see cref="bool" />.
        /// </returns>
        public bool WaitForControlEnabled()
        {
            return this._control.WaitForControlEnabled();
        }

        /// <summary>
        /// The wait for control enabled.
        /// </summary>
        /// <param name="millisecond">
        /// The millisecond.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool WaitForControlEnabled(int millisecond)
        {
            return this._control.WaitForControlEnabled(millisecond);
        }

        /// <summary>
        ///     The wait for control exist.
        /// </summary>
        /// <returns>
        ///     The <see cref="bool" />.
        /// </returns>
        public bool WaitForControlExist()
        {
            return this._control.WaitForControlExist();
        }

        /// <summary>
        /// The wait for control exist.
        /// </summary>
        /// <param name="millisecond">
        /// The millisecond.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool WaitForControlExist(int millisecond)
        {
            return this._control.WaitForControlExist(millisecond);
        }

        /// <summary>
        ///     The wait for control ready.
        /// </summary>
        /// <returns>
        ///     The <see cref="bool" />.
        /// </returns>
        public bool WaitForControlReady()
        {
            return this._control.WaitForControlReady();
        }

        /// <summary>
        /// The wait for control ready.
        /// </summary>
        /// <param name="millisecond">
        /// The millisecond.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool WaitForControlReady(int millisecond)
        {
            return this._control.WaitForControlReady(millisecond);
        }

        /// <summary>
        /// The wrap.
        /// </summary>
        /// <param name="control">
        /// The control.
        /// </param>
        public void Wrap(object control)
        {
            this._control = control as T;
            this._control.SearchProperties.AddRange(this.SearchProperties);
        }

        /// <summary>
        /// The wrap ready.
        /// </summary>
        /// <param name="control">
        /// The control.
        /// </param>
        public void WrapReady(object control)
        {
            this._control = control as T;
        }

        /// <summary>
        /// The write test output.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        public virtual void WriteTestOutput(string message)
        {
            this.Report.WriteTestOutput(message + this._control.ClassName + this._control.FriendlyName);
        }

        #endregion
    }
}